package com.wcy.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wcy.entity.User;
import com.wcy.entity.UserCollection;
import com.wcy.entity.UserRating;
import com.wcy.entity.UserRole;
import com.wcy.entity.userVo.AuthorProfile;
import com.wcy.entity.userVo.PasswordObject;
import com.wcy.entity.userVo.UserFiltered;
import com.wcy.mapper.UserCollectionMapper;
import com.wcy.mapper.UserMapper;
import com.wcy.mapper.UserRatingMapper;
import com.wcy.mapper.UserRoleMapper;
import com.wcy.service.IUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wcy.util.JwtTokenUtil;
import com.wcy.util.PasswordUtil;
import com.wcy.util.vo.AuthRequest;
import com.wcy.util.vo.AuthResponse;
import jakarta.annotation.Resource;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 吴传亿
 * @since 2025-04-28
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private UserRoleMapper userRoleMapper;
    @Resource
    private JwtTokenUtil util;
    @Autowired
    private UserCollectionMapper userCollectionMapper;
    @Autowired
    private UserRatingMapper userRatingMapper;

    @Override
    public Page<User> page(Page<User> page, Wrapper<User> wrapper){
        return userMapper.selectPage(page,wrapper);
    }

    @Override
    public AuthResponse login(AuthRequest request) {
        User user = userMapper.selectByUsername(request.getUsername());
        if(user!=null&& PasswordUtil.verifyPassword(request.getPassword(),user.getPassword())){
            userMapper.update(new User().setLastLogin(LocalDateTime.now()),new QueryWrapper<User>().eq("user_id",user.getUserId()));
            return new AuthResponse(util.generateToken(user.getUserId(),user.getUsername()), new UserFiltered(user,PasswordUtil.encodePassword(request.getRandomCode())),null);
        }
        return null;
    }


    @Override
    public Boolean register(User user) {
        if(userMapper.exists(new QueryWrapper<User>().eq("username",user.getUsername())))
            return false;
        user.setPassword(PasswordUtil.encodePassword(user.getPassword()));
        user.setCreatedAt(LocalDateTime.now());
        user.setUpdatedAt(LocalDateTime.now());
        if(userMapper.insert(user)>0&&user.getRoles()!=null){
            User dbUser = userMapper.selectOne(new QueryWrapper<User>().eq("username",user.getUsername()));
            userRoleMapper.insert(user
                    .getRoles()
                    .stream()
                    .map(e->new UserRole(dbUser.getUserId(),e.getRoleId()))
                    .collect(Collectors.toList()));
        }
        return true;
    }

    @Override
    public Boolean validate(String token) {
        return util.validateToken(token);
    }

    public boolean updateById(User user){
        if(user.getPassword()!=null&&!PasswordUtil.isBCryptEncoded(user.getPassword())){
            user.setPassword(PasswordUtil.encodePassword(user.getPassword()));
        }else {
            user.setPassword(null);
        }
        return userMapper.updateById(user)>0;
    }

    @Override
    public AuthorProfile getAuthorProfile(List<Integer> resourceIds) {
        System.out.println(resourceIds);
        if(resourceIds==null||resourceIds.isEmpty())
            return new AuthorProfile(0,0,0d);
        Long collectionCount = userCollectionMapper.selectCount(new QueryWrapper<UserCollection>().in("resource_id",resourceIds));
        List<UserRating> ratings = userRatingMapper.selectList(new QueryWrapper<UserRating>().in("resource_id",resourceIds));
        Double avgScore = ratings.stream().mapToDouble(UserRating::getRatingValue).average().orElse(0);
        return new AuthorProfile(resourceIds.size(),collectionCount.intValue(),avgScore);
    }

    @Override
    public boolean updatePassword(PasswordObject passwordObject, Integer id) {
        return userMapper.update(new User().setPassword(PasswordUtil.encodePassword(passwordObject.getNewPassword())),new QueryWrapper<User>().eq("user_id",id))>0;
    }
}